/*
    Copyright (C) 2012  Collombet

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

#include "object.h"

#include <stdlib.h>
#include <stdio.h>
#include <libio.h>

void object_create(Object** value,
                   void (*toString)(const void* value, int fd),
                   int (*equals)(const void* value, const void* operande),
                   int (*copy)(const void* value, void* ret),
                   int (*create)(void** value, void* args),
                   int (*initialize)(void* value, void* args),
                   void (*clear)(void* value),
                   void (*destroy)(void** value))
{
    (*value) = (Object*) malloc(sizeof(Object));
    object_initialize((*value),
                      toString,
                      equals,
                      copy,
                      create,
                      initialize,
                      clear,
                      destroy);
}

void object_initialize(Object* value,
                       void (*toString)(const void* value, int fd),
                       int (*equals)(const void* value, const void* operande),
                       int (*copy)(const void* value, void* ret),
                       int (*create)(void** value, void* args),
                       int (*initialize)(void* value, void* args),
                       void (*clear)(void* value),
                       void (*destroy)(void** value))
{
    value->toString = toString;
    value->equals = equals;
    value->copy = copy;
    value->create = create;
    value->initialize = initialize;
    value->clear = clear;
    value->destroy = destroy;
}

void object_copy(const Object* value, Object* ret)
{
    ret->toString = value->toString;
    ret->equals = value->equals;
    ret->copy = value->copy;
    ret->create = value->create;
    ret->initialize = value->initialize;
    ret->clear = value->clear;
    ret->destroy = value->destroy;
}

void object_clear(Object* value)
{
    value->toString = NULL;
    value->equals = NULL;
    value->copy = NULL;
    value->create = NULL;
    value->initialize = NULL;
    value->clear = NULL;
    value->destroy = NULL;
}

void object_destroy(Object** value)
{
    object_clear((*value));
    free((*value));
    (*value) = NULL;
}

Object object_getObject()
{
    object_initialize(&_object_Object,
                      object_toString,
                      object_equals,
                      _object_copy,
                      _object_create,
                      _object_initialize,
                      _object_clear,
                      _object_destroy);
    return _object_Object;
}

void object_toString(const void* value, int fd)
{
    char buf[80];
    int size = sprintf(buf,"object");
    write(fd,buf,size);
}

int _object_copy(const void* value, void* ret)
{
    _object_initialize(ret,(void*)(&value));
    return 1;
}

int _object_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(Object));
    _object_initialize((*value),args);
    return 1;
}

int _object_initialize(void* value, void* args)
{
    Object* obj = (Object*) value;
    if(args != NULL)
    {
        void** _args = args;
        object_initialize(obj,
                          (void (*)(const void* , int ))_args[0],
                          (int (*)(const void* , const void* ))_args[1],
                          (int (*)(const void* , void* )) _args[2],
                          (int (*)(void** , void* ))_args[3],
                          (int (*)(void* , void* ))_args[4],
                          (void (*)(void* ))_args[5],
                          (void (*)(void** ))_args[6]);
        return 1;
    }
    else
        return 0;
}

void _object_destroy(void** value)
{
    _object_clear((*value));
    (*value) = NULL;
}

void _object_clear(void* value)
{
    Object* obj = (Object*) value;
    object_clear(obj);
}

int object_equals(const void* value, const void* operande)
{
    Object* obj = (Object*) value;
    Object* obj_comp = (Object*) operande;
    if(((*obj).initialize == (*obj_comp).initialize) &&
            ((*obj).clear == (*obj_comp).clear) &&
            ((*obj).copy == (*obj_comp).copy) &&
            ((*obj).create == (*obj_comp).create) &&
            ((*obj).destroy == (*obj_comp).destroy) &&
            ((*obj).equals == (*obj_comp).equals) &&
            ((*obj).toString == (*obj_comp).toString))
        return 1;
    else
        return 0;
}

const Object object_getInt()
{
    object_initialize(&_object_int,
                      _int_toString,
                      _int_equals,
                      _int_copy,
                      _int_create,
                      _int_initialize,
                      _int_clear,
                      _int_destroy);
    return _object_int;
}

void _int_toString(const void* value, int fd)
{
    int* obj = (int*) value;
    char buf[80];
    int size = sprintf(buf,"%d",(*obj));
    write(fd,buf,size);
}

int _int_equals(const void* value, const void* operande)
{
    int* obj = (int*) value;
    int* obj_comp = (int*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _int_copy(const void* value, void* ret)
{
    *((int*)ret) = *((int*)value);
    return 1;
}

int _int_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(int));
    _int_initialize((*value),args);
    return 1;
}

int _int_initialize(void* value, void* args)
{
    int* obj = (int*) value;
    if(args == NULL)
        (*obj) = 0;
    else
        (*obj) = (int*)((void**)args)[0];
    return 1;
}

void _int_destroy(void** value)
{
    _int_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _int_clear(void* value)
{
    int* obj = (int*) value;
    (*obj) = 0;
}

Object object_getDouble()
{
    object_initialize(&_object_double,
                      _double_toString,
                      _double_equals,
                      _double_copy,
                      _double_create,
                      _double_initialize,
                      _double_clear,
                      _double_destroy);
    return _object_double;
}

void _double_toString(const void* value, int fd)
{
    char buf[80];
    double* obj = (double*) value;
    int size = sprintf(buf,"%f",(*obj));
    write(fd,buf, size);
}

int _double_equals(const void* value, const void* operande)
{
    double* obj = (double*) value;
    double* obj_comp = (double*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _double_copy(const void* value, void* ret)
{
    *((double*)ret) = *((double*)value);
    return 1;
}

int _double_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(double));
    _double_initialize((*value),args);
    return 1;
}

int _double_initialize(void* value, void* args)
{
    double* obj = (double*) value;
    if(args == NULL)
        (*obj) = 0;
    else
        value = ((void**)args)[0];
    return 1;
}

void _double_destroy(void** value)
{
    _double_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _double_clear(void* value)
{
    double* obj = (double*) value;
    (*obj) = 0;
}


Object object_getFloat()
{

    object_initialize(&_object_float,
                      _float_toString,
                      _float_equals,
                      _float_copy,
                      _float_create,
                      _float_initialize,
                      _float_clear,
                      _float_destroy);

    return _object_float;
}

void _float_toString(const void* value, int fd)
{
    char buf[80];
    float* obj = (float*) value;
    int size = sprintf(buf,"%f",(*obj));
    write(fd,buf,size);
}

int _float_equals(const void* value, const void* operande)
{
    float* obj = (float*) value;
    float* obj_comp = (float*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _float_copy(const void* value, void* ret)
{
    *((float*)ret) = *((float*)value);
    return 1;
}

int _float_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(float));
    _float_initialize((*value),args);
    return 1;
}

int _float_initialize(void* value, void* args)
{
    float* obj = (float*) value;
    if(args == NULL)
    {
        (*obj) = 0;
    }
    else
    {
        value = ((void**)args)[0];
    }
    return 1;
}

void _float_destroy(void** value)
{
    _float_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _float_clear(void* value)
{
    float* obj = (float*) value;
    (*obj) = 0;
}


Object object_getLong()
{

    object_initialize(&_object_long,
                      _long_toString,
                      _long_equals,
                      _long_copy,
                      _long_create,
                      _long_initialize,
                      _long_clear,
                      _long_destroy);

    return _object_long;
}

void _long_toString(const void* value, int fd)
{
    char buf[80];
    long* obj = (long*) value;
    int size = sprintf(buf,"%ld",(*obj));
    write(fd,buf, size);
}

int _long_equals(const void* value, const void* operande)
{
    long* obj = (long*) value;
    long* obj_comp = (long*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _long_copy(const void* value, void* ret)
{
    *((long*)ret) = *((long*)value);
    return 1;
}

int _long_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(long));
    _long_initialize((*value),args);
    return 1;
}

int _long_initialize(void* value, void* args)
{
    long* obj = (long*) value;
    if(args == NULL)
    {
        (*obj) = 0;
    }
    else
    {
        value = ((void**)args)[0];
    }
    return 1;
}

void _long_destroy(void** value)
{
    _long_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _long_clear(void* value)
{
    long* obj = (long*) value;
    (*obj) = 0;
}


Object object_getShort()
{

    object_initialize(&_object_short,
                      _short_toString,
                      _short_equals,
                      _short_copy,
                      _short_create,
                      _short_initialize,
                      _short_clear,
                      _short_destroy);

    return _object_short;
}

void _short_toString(const void* value, int fd)
{
    char buf[80];
    short* obj = (short*) value;
    int size = sprintf(buf,"%d",(*obj));
    write(fd,buf, size);
}

int _short_equals(const void* value, const void* operande)
{
    short* obj = (short*) value;
    short* obj_comp = (short*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _short_copy(const void* value, void* ret)
{
    *((short*)ret) = *((short*)value);
    return 1;
}

int _short_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(short));
    _short_initialize((*value),args);
    return 1;
}

int _short_initialize(void* value, void* args)
{
    short* obj = (short*) value;
    if(args == NULL)
    {
        (*obj) = 0;
    }
    else
    {
        value = ((void**)args)[0];
    }
    return 1;
}

void _short_destroy(void** value)
{
    _short_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _short_clear(void* value)
{
    short* obj = (short*) value;
    (*obj) = 0;
}


Object object_getChar()
{

    object_initialize(&_object_char,
                      _char_toString,
                      _char_equals,
                      _char_copy,
                      _char_create,
                      _char_initialize,
                      _char_clear,
                      _char_destroy);

    return _object_char;
}

void _char_toString(const void* value, int fd)
{
    char buf[80];
    int size = sprintf(buf,"%s:80",(const char*)value);
    write(fd,buf, size);
}

int _char_equals(const void* value, const void* operande)
{
    char* obj = (char*) value;
    char* obj_comp = (char*) operande;
    if((*obj) == (*obj_comp))
        return 1;
    else
        return 0;
}

int _char_copy(const void* value, void* ret)
{
    *((char*)ret) = *((char*)value);
    return 1;
}

int _char_create(void** value, void* args)
{
    (*value) = (void*) malloc(sizeof(char));
    _char_initialize((*value),args);
    return 1;
}

int _char_initialize(void* value, void* args)
{
    char* obj = (char*) value;
    if(args == NULL)
    {
        (*obj) = '\0';
    }
    else
    {
        value = ((void**)args)[0];
    }
    return 1;
}

void _char_destroy(void** value)
{
    _char_clear((*value));
    free((*value));
    (*value) = NULL;
}

void _char_clear(void* value)
{
    char* obj = (char*) value;
    (*obj) = 0;
}
